package com.zt.service.impl;


import com.zt.config.MinioConfig;
import com.zt.config.MinioConfigProperties;
import com.zt.service.FileStorageService;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

/**
 * 文件存储服务实现类，使用MinIO作为文件存储后端。
 */
@EnableConfigurationProperties(MinioConfigProperties.class)
@Import(MinioConfig.class)
@Service
public class FileStorageServiceImpl implements FileStorageService {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfigProperties minioConfigProperties;

    /**
     * 上传HTML文件到MinIO存储桶。
     *
     * @param fileName    原始文件名。
     * @param inputStream 文件输入流。
     * @return 文件在MinIO中的URL。
     * @throws IOException                如果发生I/O错误。
     * @throws ServerException            如果服务器端发生错误。
     * @throws InvalidBucketNameException 如果存储桶名称无效。
     * @throws InsufficientDataException  如果提供的数据不足以完成请求。
     * @throws ErrorResponseException     如果服务器返回错误响应。
     * @throws NoSuchAlgorithmException   如果指定的算法不存在。
     * @throws InvalidKeyException        如果指定的密钥无效。
     * @throws InvalidResponseException   如果服务器返回无效响应。
     * @throws XmlParserException         如果XML解析失败。
     * @throws InternalException          如果发生内部错误。
     */
    @Override
    public String uploadHtmlFile(String fileName, InputStream inputStream) throws IOException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 生成唯一文件名
        fileName = UUID.randomUUID() + fileName;

        // 构建上传参数
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .object(fileName) // 文件名
                .bucket(minioConfigProperties.getBucket())
                .contentType("text/html")
                .stream(inputStream, inputStream.available(), -1)
                .build();

        // 执行上传
        minioClient.putObject(putObjectArgs);

        // 返回文件访问URL
        return minioClient.getObjectUrl(putObjectArgs.bucket(), putObjectArgs.object());
    }

    /**
     * 上传图片文件到MinIO存储桶。
     *
     * @param fileName    原始文件名。
     * @param inputStream 文件输入流。
     * @return 文件在MinIO中的URL。
     * @throws IOException                如果发生I/O错误。
     * @throws ServerException            如果服务器端发生错误。
     * @throws InvalidBucketNameException 如果存储桶名称无效。
     * @throws InsufficientDataException  如果提供的数据不足以完成请求。
     * @throws ErrorResponseException     如果服务器返回错误响应。
     * @throws NoSuchAlgorithmException   如果指定的算法不存在。
     * @throws InvalidKeyException        如果指定的密钥无效。
     * @throws InvalidResponseException   如果服务器返回无效响应。
     * @throws XmlParserException         如果XML解析失败。
     * @throws InternalException          如果发生内部错误。
     */
    @Override
    public String uploadImageFile(String fileName, InputStream inputStream) throws IOException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 生成唯一文件名
        fileName = UUID.randomUUID() + fileName;

        // 构建上传参数
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .object(fileName) // 文件名
                .bucket(minioConfigProperties.getBucket())
                .contentType("image/jpg")
                .stream(inputStream, inputStream.available(), -1)
                .build();

        // 执行上传
        minioClient.putObject(putObjectArgs);

        // 返回文件访问URL
        return minioClient.getObjectUrl(putObjectArgs.bucket(), putObjectArgs.object());
    }

    /**
     * 上传图片字节数组到MinIO存储桶。
     *
     * @param fileName   原始文件名。
     * @param imageBytes 图片字节数组。
     * @return 文件在MinIO中的URL。
     * @throws IOException                如果发生I/O错误。
     * @throws ServerException            如果服务器端发生错误。
     * @throws InvalidBucketNameException 如果存储桶名称无效。
     * @throws InsufficientDataException  如果提供的数据不足以完成请求。
     * @throws ErrorResponseException     如果服务器返回错误响应。
     * @throws NoSuchAlgorithmException   如果指定的算法不存在。
     * @throws InvalidKeyException        如果指定的密钥无效。
     * @throws InvalidResponseException   如果服务器返回无效响应。
     * @throws XmlParserException         如果XML解析失败。
     * @throws InternalException          如果发生内部错误。
     */
    @Override
    public String uploadImageBytes(String fileName, byte[] imageBytes) throws IOException, ServerException, InvalidBucketNameException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 生成唯一文件名
        fileName = UUID.randomUUID() + fileName;

        // 使用ByteArrayInputStream将字节数组转换为输入流
        try (InputStream inputStream = new ByteArrayInputStream(imageBytes)) {
            // 构建上传参数
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(fileName)
                    .bucket(minioConfigProperties.getBucket())
                    .contentType("image/png") // 默认使用PNG格式
                    .stream(inputStream, imageBytes.length, -1)
                    .build();

            // 执行上传
            minioClient.putObject(putObjectArgs);

            // 返回文件访问URL
            return minioClient.getObjectUrl(putObjectArgs.bucket(), putObjectArgs.object());
        }
    }
}
